/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.scheduler.specific.pbs.status;

import java.util.Collection;
import java.util.LinkedList;

import jp.aist.gtrc.plus.scheduler.status.QInstanceStatus;
import jp.aist.gtrc.plus.scheduler.status.QueueStatus;
import jp.aist.gtrc.plus.scheduler.status.QueueStatusBase;

//	attr			value
//	-----------------------------
//	batch			7
//		queue_type		Execution
//		total_jobs		0
//		...
//	workq			7
//		queue_type		Execution
//		total_jobs		1
//		state_count		Transit:0 Queued:1 Held:0 Waiting:0 Running:0 Exiting:0
//		resources_assigned	ncpus	0
//		resources_assigned	nodect	0
//		enabled			True
//		started			True
//		Priority			0				<<< THIS IS OPTIONAL VALUE, use qmgr


public class PBSQueueStatus extends QueueStatusBase implements QueueStatus, QInstanceStatus, StatusMap {

	private final StatusMap map;

	public PBSQueueStatus(String name){

		map = new StatusMapImpl(name);

	}

	public String getQueueType(){

		return getStatus("queue_type");

	}

	public boolean isExecution(){

		return getQueueType().equals("Execution");

	}

	public boolean isEnabled(){

		return getStatus("enabled").equals("True");

	}

	public boolean isStarted(){

		return getStatus("started").equals("True");

	}

	public boolean isReadyToUse(){

		return isExecution() && isEnabled() && isStarted();

	}

	public int getTotalJobs(){

		return Integer.parseInt(getStatus("total_jobs"));

	}

	public int getStateCount(String type){

		String s = getStatus("state_count");

		for (String t : s.split("\\s")) {
			if (t.startsWith(type)) {
				// t is "Queued:1" (if type is "Queued")
				// u is "1" (plus 1 means length of ":")
				String u = t.substring(type.length() + 1);
				return Integer.parseInt(u);
			}
		}

		return 0;	// Not found

	}

	public int getQueuedJobs(){

		return getStateCount("Queued");

	}

	public int getRunningJobs(){

		return getStateCount("Running");

	}

	public int getPriority() {

		/*
		 * If you want to use queue priority, set it by qmgr such as
		 * 		% su
		 * 		# qmgr
		 * 		Qmgr: set queue QUEUE_NAME priority = VALUE
		 * 		Qmgr: quit
		 * If not set, "Priority" doesn't appear.
		 */
		String p = getStatus("Priority");
		if (p != UNKNOWN_STATUS)
			return Integer.parseInt(p);
		else
			return 0;		// default normal priority

	}

	public boolean isSuspended() {

		return (!isEnabled() || !isStarted());

	}


	/*
	 * NOTE: We handle PBSQueueStatus as not only QueueStatus
	 * but also QInstanceStatus.
	 * Below methods are pseudo-implemented.
	 */
	public Collection<QInstanceStatus> getAllQInstances() {

		/*
		 * NOTE: return PBSQueueStatus as QInstanceStatus element.
		 */
		LinkedList<QInstanceStatus> list = new LinkedList<QInstanceStatus>();
		list.add(this);
		return list;

	}

	public String getQname() {

		return getName();
	}

	public String getHostname() {

		/*
		 * One PBS(Torque) queue uses all exec-nodes always.
		 */
		return "ALLHOSTS";

	}

	public int getUsedSlotNum() {

		return getTotalJobs();

	}

	public int getAllSlotNum() {

		return 1;

	}

	public String getName() {
		return map.getName();
	}

	public String getStatus(String attr) {
		return map.getStatus(attr);
	}

	public String getStatus(String name, String attr) {
		return map.getStatus(name, attr);
	}

	public StatusMap getStatusMap(String name) {
		return map.getStatusMap(name);
	}

	public void putStatus(String attr, String value) {
		map.putStatus(attr, value);
	}

}
